<template>
  <div>
    <el-dialog title="规则编辑" width="50%" :visible.sync="enable" :close-on-click-modal="false">
      <el-form label-width="100px">
        <el-form-item label="协议">
          <el-col :span="16">
            <el-select v-model="model.protocol" placeholder="请选择" style="width: 100%;" @change="actionProtocolChanged">
              <el-option key="all" label="All" :value="null"></el-option>
              <el-option key="tcp" label="TCP" value="tcp"></el-option>
              <el-option key="udp" label="UDP" value="udp"></el-option>
              <el-option key="udplite" label="UDPLITE" value="udplite"></el-option>
              <el-option key="icmp" label="ICMP" value="icmp"></el-option>
              <el-option key="icmpv6" label="ICMPV6" value="icmpv6"></el-option>
              <el-option key="esp" label="ESP" value="esp"></el-option>
              <el-option key="ah" label="AH" value="ah"></el-option>
              <el-option key="sctp" label="SCTP" value="sctp"></el-option>
              <el-option key="mh" label="MH" value="mh"></el-option>
            </el-select>
          </el-col>
          <el-col class="line" :span="4">
            &nbsp;
            <el-button 
              :disabled=" undefined == protocols[model.protocol]"
              @click="actionEditRuleProtocolConfig"
            >配置</el-button>
          </el-col>
          <el-col :span="4">
            <el-checkbox v-model="model['!protocol']">排除</el-checkbox>
          </el-col>
        </el-form-item>
        <el-form-item label="来源地址">
          <el-col :span="19">
            <el-select v-model="model.source" filterable allow-create default-first-option multiple style="width:100%;">
              <el-option label="0.0.0.0/0" value="0.0.0.0/0"></el-option>
              <el-option label="10.0.0.0/8" value="10.0.0.0/8"></el-option>
              <el-option label="172.16.0.0/12" value="172.16.0.0/12"></el-option>
              <el-option label="192.168.0.0/16" value="192.168.0.0/16"></el-option>
            </el-select>
          </el-col>
          <el-col class="line" :span="1">&nbsp;</el-col>
          <el-col :span="4">
            <el-checkbox v-model="model['!source']">排除</el-checkbox>
          </el-col>
        </el-form-item>
        <el-form-item label="目标地址">
          <el-col :span="19">
            <el-select v-model="model.destination" filterable allow-create default-first-option multiple style="width:100%;">
              <el-option label="0.0.0.0/0" value="0.0.0.0/0"></el-option>
              <el-option label="10.0.0.0/8" value="10.0.0.0/8"></el-option>
              <el-option label="172.16.0.0/12" value="172.16.0.0/12"></el-option>
              <el-option label="192.168.0.0/16" value="192.168.0.0/16"></el-option>
            </el-select>
          </el-col>
          <el-col class="line" :span="1">&nbsp;</el-col>
          <el-col :span="4">
            <el-checkbox v-model="model['!destination']">排除</el-checkbox>
          </el-col>
        </el-form-item>
        <el-form-item label="输入接口" v-if="-1 != ['INPUT','FORWARD','PREROUTING'].indexOf(chain)">
          <el-col :span="19">
            <el-select v-model="model.inInterface" placeholder="请选择" style="width: 100%;" filterable allow-create default-first-option>
              <el-option v-for="theInterface in interfaces" 
                :key="theInterface" :label="theInterface" :value="theInterface"
              ></el-option>
            </el-select>
          </el-col>
          <el-col class="line" :span="1">&nbsp;</el-col>
          <el-col :span="4">
            <el-checkbox v-model="model['!inInterface']">排除</el-checkbox>
          </el-col>
        </el-form-item>
        <el-form-item label="输出接口" v-if="-1 != ['FORWARD','OUTPUT','POSTROUTING'].indexOf(chain)">
          <el-col :span="19">
            <el-select v-model="model.outInterface" placeholder="请选择" style="width: 100%;" filterable allow-create default-first-option>
              <el-option v-for="theInterface in interfaces" 
                :key="theInterface" :label="theInterface" :value="theInterface"
              ></el-option>
            </el-select>
          </el-col>
          <el-col class="line" :span="1">&nbsp;</el-col>
          <el-col :span="4">
            <el-checkbox v-model="model['!outInterface']">排除</el-checkbox>
          </el-col>
        </el-form-item>
        
        <!-- 匹配 -->
        <el-form-item label="匹配">
          <el-row v-for="(item, index) in model.matches" :key="item.key" style="margin-bottom:5px;">
            <el-col :span="16">
              <el-input :value="item.module" disabled></el-input>
            </el-col>
            <el-col class="line" :span="4">
              &nbsp;
              <el-button @click="actionRuleMatchConfigRemove(index)">移除</el-button>
            </el-col>
            <el-col :span="4"></el-col>
          </el-row>
          <el-col :span="16">
            <el-select placeholder="请选择" v-model="matchModule" style="width: 100%;">
              <el-option v-for="(match, matchKey) in matches" 
                :key="matchKey" :label="matchKey" :value="matchKey"
              ></el-option>
            </el-select>
          </el-col>
          <el-col class="line" :span="4">
            &nbsp;
            <el-button :disabled="null == matchModule" @click="actionEditRuleMatchConfig">  
              <span v-if="null == matchModule || 0 < matches[matchModule].params.length">配置</span>
              <span v-if="null != matchModule && 0 == matches[matchModule].params.length">添加</span>
            </el-button>
          </el-col>
          <el-col :span="4"></el-col>
        </el-form-item>

        <el-form-item label="调用 (-j)">
          <el-col :span="16">
            <el-select placeholder="请选择" v-model="model.target" style="width: 100%;" v-if="null != iptables">
              <el-option v-for="buildinTarget in buildinTargets" 
                :key="buildinTarget" :label="buildinTarget" :value="buildinTarget"
              ></el-option>
              <el-option v-for="(chain, chainKey) in iptables[table]" 
                :key="chainKey" :label="chainKey" :value="chainKey"
              ></el-option>
              <template v-for="(target, targetKey) in targets">
                <el-option v-if="
                  (undefined == target.table || target.table == table) 
                  && (undefined == target.chain || -1 != target.chain.indexOf(chain))
                  && (undefined == target.protocol || -1 != target.protocol.indexOf(model.protocol))"
                  :key="targetKey" :label="targetKey" :value="targetKey"
                ></el-option>
              </template>
            </el-select>
          </el-col>
          <el-col class="line" :span="4">
            &nbsp;
            <el-button 
              :disabled="undefined == targets[model.target] || 0 == targets[model.target].params.length"
              @click="actionEditRuleTargetConfig"
            >配置</el-button>
          </el-col>
          <el-col :span="4"></el-col>
        </el-form-item>
        <el-form-item label="执行 (-g)">
          <el-col :span="19">
            <el-select placeholder="请选择" v-model="model.goto" style="width: 100%;" v-if="null != iptables" clearable>
              <el-option v-for="(chain, chainKey) in iptables[table]" 
                :key="chainKey" :label="chainKey" :value="chainKey"
              ></el-option>
            </el-select>
          </el-col>
          <el-col class="line" :span="1">&nbsp;</el-col>
          <el-col :span="4"></el-col>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="enable = false">取 消</el-button>
        <el-button type="primary" @click="actionRuleAdd">确 定</el-button>
      </span>
    </el-dialog>
    <parameter-editor ref="paramEditor"></parameter-editor>
  </div>
</template>
<script>
import IptablesMatchConfig from './IptablesMatchConfig.js'
import IptablesTargetConfig from './IptablesTargetConfig.js'
import IptablesProtocolConfig from './IptablesProtocolConfig.js'
import IptablesParameterEditor from './IptablesParameterEditor.vue'
import IptablesRuleAddCmdGenerator from './IptablesRuleAddCmdGenerator.js'
export default {
    name : 'RuleEdit',
    components : {
        'parameter-editor' : IptablesParameterEditor,
    },
    data() {
        return {
            idcounter : 0,

            client : null,
            iptables : null,
            table : null,
            chain : null,
            enable : false,
            model : {},

            interfaces : [],
            matches : IptablesMatchConfig,
            targets : IptablesTargetConfig,
            buildinTargets : ['ACCEPT','DROP','RETURN'],
            protocols : IptablesProtocolConfig,
            matchModule : null,

            actResolve : null,
            actReject : null,
        };
    },
    methods : {
        /** 协议变更 */
        actionProtocolChanged() {
            this.model.protocolConfig = {};
        },
        /** 协议配置 */
        async actionEditRuleProtocolConfig () {
            this.$refs.paramEditor.setModel(this.model.protocolConfig);
            this.$refs.paramEditor.config = this.protocols[this.model.protocol];
            await this.$refs.paramEditor.edit();
            this.model.protocolConfig = this.$refs.paramEditor.model;
        },






        /** 打开编辑框 */
        open() {
            let $this = this;
            return new Promise(async ( resolve, reject ) => {
                $this.actResolve = resolve;
                $this.actReject = reject;

                let list = await $this.client.exec('ifconfig -s');
                list = list.split('\n');
                list.shift();
                list.pop();
                
                $this.interfaces = [];
                for ( let i=0; i<list.length; i++ ) {
                    let name = list[i].split(' ')[0];
                    $this.interfaces.push(name);
                }
                
                $this.model = {};
                $this.enable = true;
            });
        },

        /** 匹配移除 */
        actionRuleMatchConfigRemove ( index ) {
            this.model.matches.splice(index, 1);
            this.$forceUpdate();
        },

        /** 匹配配置 */
        async actionEditRuleMatchConfig() {
            this.$refs.paramEditor.config = this.matches[this.matchModule];
            await this.$refs.paramEditor.edit();
            if ( undefined == this.model.matches ) {
                this.model.matches = [];
            }
            this.model.matches.push({
                key : this.idcounter,
                module : this.matchModule,
                config : this.$refs.paramEditor.model
            });
            this.idcounter ++;
            this.matchModule = null;
        },

        /** 目标配置 */
        async actionEditRuleTargetConfig() {
            this.$refs.paramEditor.config = this.targets[this.model.target];
            await this.$refs.paramEditor.edit();
            this.model.targetConfig = this.$refs.paramEditor.model;
        },

        /**  */
        actionRuleAdd(){
            this.model.chain = this.chain;
            this.model.table = this.table;
            let generator = new IptablesRuleAddCmdGenerator(this.model);
            if ( !generator.generate() ) {
                this.$message.error(generator.error);
                return false;
            }
            
            let $this = this;
            let cmd = generator.cmd;
            this.$confirm(cmd, '命令执行', {
                confirmButtonText: '执行',
                cancelButtonText: '取消',
                type: 'warning'
            }).then(async () => {
                await $this.client.exec(cmd);
                $this.enable = false;
                $this.actResolve();
            });
        }
    }
}
</script>